@(diffs: Seq[gitbucket.core.util.JGitUtil.DiffInfo],
  repository: gitbucket.core.service.RepositoryService.RepositoryInfo,
  newCommitId: Option[String],
  oldCommitId: Option[String],
  showIndex: Boolean,
  issueId: Option[Int],
  hasWritePermission: Boolean,
  showLineNotes: Boolean)(implicit context: gitbucket.core.controller.Context)
@import gitbucket.core.view.helpers
@import org.eclipse.jgit.diff.DiffEntry.ChangeType
@if(showIndex){
  <div class="pull-right" style="margin-bottom: 10px;">
    <div class="btn-group" data-toggle="buttons-radio">
      <input type="button" id="btn-unified" class="btn btn-default btn-small active" value="Unified">
      <input type="button" id="btn-split" class="btn btn-default btn-small" value="Split">
    </div>
  </div>
  Showing <a href="javascript:void(0);" id="toggle-file-list">@diffs.size changed @helpers.plural(diffs.size, "file")</a>
  <ul id="commit-file-list" style="display: none;">
  @diffs.zipWithIndex.map { case (diff, i) =>
    <li@if(i > 0){ class="border"}>
      <span class="pull-right diffstat" data-diff-id="@i"></span>
      <a href="#diff-@i">
        @if(diff.changeType == ChangeType.COPY || diff.changeType == ChangeType.RENAME){
          <i class="octicon octicon-diff-renamed"></i> @diff.oldPath -> @diff.newPath
        }
        @if(diff.changeType == ChangeType.ADD){
          <i class="octicon octicon-diff-added"></i> @diff.newPath
        }
        @if(diff.changeType == ChangeType.MODIFY){
          <i class="octicon octicon-diff-modified"></i> @diff.newPath
        }
        @if(diff.changeType == ChangeType.DELETE){
          <i class="octicon octicon-diff-removed"></i> @diff.oldPath
        }
      </a>
    </li>
    }
  </ul>
}
@diffs.zipWithIndex.map { case (diff, i) =>
  <a name="diff-@i"></a>
  <table class="table table-bordered diff-outside" commitId="@newCommitId" fileName="@diff.newPath" data-diff-id="@i">
    <tr>
      <th style="font-weight: normal;" class="box-header">
        @if(diff.changeType == ChangeType.COPY || diff.changeType == ChangeType.RENAME){
          @if(newCommitId.isDefined){
            <div class="pull-right align-right">
              <label class="no-margin"><input type="checkbox" class="ignore-whitespace" value="1"/> Ignore Space</label>
              <label class="no-margin"><input type="checkbox" class="toggle-notes" checked> Show notes</label>
              <a href="@helpers.url(repository)/blob/@newCommitId.get/@diff.newPath" class="btn btn-default btn-sm" title="View the whole file at version @newCommitId.get.substring(0, 10)" data-toggle="tooltip">View</a>
            </div>
          }
          <span class="diffstat"><i class="octicon octicon-diff-renamed"></i></span>
          <span class="monospace">@diff.oldPath → @diff.newPath</span>
        }
        @if(diff.changeType == ChangeType.ADD || diff.changeType == ChangeType.MODIFY){
          @if(newCommitId.isDefined){
            <div class="pull-right align-right">
              <label class="no-margin"><input type="checkbox" class="ignore-whitespace" value="1"/> Ignore Space</label>
              <label class="no-margin"><input type="checkbox" class="toggle-notes" checked> Show notes</label>
              <a href="@helpers.url(repository)/blob/@newCommitId.get/@diff.newPath" class="btn btn-default btn-sm" title="View the whole file at version @newCommitId.get.substring(0, 10)" data-toggle="tooltip">View</a>
            </div>
          }
          <span class="diffstat">
          @if(diff.changeType == ChangeType.ADD){
            <i class="octicon octicon-diff-added"></i>
          } else {
            <i class="octicon octicon-diff-modified"></i>
          }
          </span>
          <span class="monospace">@diff.newPath</span>
        }
        @if(diff.changeType == ChangeType.DELETE){
          @if(oldCommitId.isDefined){
            <div class="pull-right align-right">
              <label class="no-margin"><input type="checkbox" class="toggle-notes" checked> Show notes</label>
              <a href="@helpers.url(repository)/blob/@oldCommitId.get/@diff.oldPath" class="btn btn-default btn-sm" title="View the whole file at version @oldCommitId.get.substring(0, 10)" data-toggle="tooltip">View</a>
            </div>
          }
          <span class="diffstat"><i class="octicon octicon-diff-removed"></i></span>
          <span class="monospace">@diff.oldPath</span>
        }
        @if(diff.oldMode != diff.newMode){
          <span class="monospace">@diff.oldMode → @diff.newMode</span>
        }
      </th>
    </tr>
    <tr>
      <td style="padding: 0;">
        @if(diff.oldObjectId == diff.newObjectId){
          @if(diff.oldPath != diff.newPath){
            <div class="diff-same">File renamed without changes</div>
          } else {
            <div class="diff-same">File mode changed</div>
          }
        } else {
          @if(diff.newContent != None || diff.oldContent != None){
            <div id="diffText-@i" class="diffText"></div>
            <textarea id="newText-@i" style="display: none;" data-file-name="@diff.oldPath">@diff.newContent.getOrElse("")</textarea>
            <textarea id="oldText-@i" style="display: none;" data-file-name="@diff.newPath">@diff.oldContent.getOrElse("")</textarea>
          } else {
            @if(diff.newIsImage || diff.oldIsImage){
              <div class="diff-image-render diff2up">
              @if(oldCommitId.isDefined && diff.oldIsImage){
                <div class="diff-image-frame diff-old"><img src="@helpers.url(repository)/raw/@oldCommitId.get/@diff.oldPath" class="diff-image" onload="onLoadedDiffImages(this)" style="display:none" /></div>
              } else {
                @if(diff.changeType != ChangeType.ADD){
                  <div style="padding: 12px;">Not supported</div>
                }
              }
              @if(newCommitId.isDefined && diff.newIsImage){
                <div class="diff-image-frame diff-new"><img src="@helpers.url(repository)/raw/@newCommitId.get/@diff.newPath" class="diff-image" onload="onLoadedDiffImages(this)" style="display:none" /></div>
              } else {
                @if(diff.changeType != ChangeType.DELETE){
                  <div style="padding: 12px;">Not supported</div>
                }
              }
              </div>
            } else {
              @if(diff.tooLarge){
                <div style="padding: 12px;">Too large</div>
              } else {
                <div style="padding: 12px;">Not supported</div>
              }
            }
          }
        }
      </td>
    </tr>
  </table>
}
<script type="text/javascript" src="@helpers.assets/vendors/jsdifflib/difflib.js"></script>
<link href="@helpers.assets/vendors/jsdifflib/diffview.css" type="text/css" rel="stylesheet" />
<script>
$(function(){
  @if(showIndex){
    $('#toggle-file-list').click(function(){
      $('#commit-file-list').toggle();
      if($(this).val() == 'Show file list'){
        $(this).val('Hide file list');
      } else {
        $(this).val('Show file list');
      }
    });
  }

  // Render diffs as unified mode initially
  if(("&"+location.search.substring(1)).indexOf("&w=1")!=-1){
    $('.ignore-whitespace').prop('checked',true);
  }
  window.viewType=1;
  if(("&"+location.search.substring(1)).indexOf("&diff=split")!=-1){
    $('.container').removeClass('container').addClass('container-wide');
    window.viewType=0;
  }
  renderDiffs();

  $('#btn-unified').click(function(){
    window.viewType=1;
    $('.container-wide').removeClass('container-wide').addClass('container');
    renderDiffs();
  });

  $('#btn-split').click(function(){
    window.viewType=0;
    $('.container').removeClass('container').addClass('container-wide');
    renderDiffs();
  });

  $('.toggle-notes').change(function() {
    if (!$(this).prop('checked')) {
      $(this).closest('table').find('.not-diff.inline-comment-form').remove();
    }
    $(this).closest('table').find('.not-diff').toggle();
  });
  $('.ignore-whitespace').change(function() {
    renderOneDiff($(this).closest("table").find(".diffText"), viewType);
  });

  function getInlineContainer(where) {
    if (viewType == 0) {
      if (where === 'new') {
        return $('<tr class="not-diff"><td colspan="2"></td><td colspan="2" class="comment-box-container"></td></tr>');
      } else if (where === 'old') {
        return $('<tr class="not-diff"><td colspan="2" class="comment-box-container"></td><td colspan="2"></td></tr>');
      }
    }
    return $('<tr class="not-diff"><td colspan="3" class="comment-box-container"></td></tr>');
  }
  if (typeof $('#show-notes')[0] !== 'undefined' && !$('#show-notes')[0].checked) {
    $('#comment-list').children('.inline-comment').hide();
  }
  $('.diff-outside').on('click','table.diff .add-comment',function() {
    var $this = $(this),
    $tr = $this.closest('tr'),
    $check = $this.closest('table:not(.diff)').find('.toggle-notes');
    if (!$check.prop('checked')) {
      $check.prop('checked', true).trigger('change');
    }
    if (!$tr.nextAll(':not(.not-diff):first').prev().hasClass('inline-comment-form')) {
      var commitId = $this.closest('.table-bordered').attr('commitId'),
      fileName = $this.closest('.table-bordered').attr('fileName'),
      oldLineNumber, newLineNumber,
      url = '@helpers.url(repository)/commit/' + commitId + '/comment/_form?fileName=' + fileName@issueId.map { id => + '&issueId=@id' };
      if (viewType == 0) {
        oldLineNumber = $this.parent().prev('.oldline').attr('line-number');
        newLineNumber = $this.parent().prev('.newline').attr('line-number');
      } else {
        oldLineNumber = $this.parent().prevAll('.oldline').attr('line-number');
        newLineNumber = $this.parent().prevAll('.newline').attr('line-number');
      }
      if (!isNaN(oldLineNumber) && oldLineNumber) {
        url += ('&oldLineNumber=' + oldLineNumber)
      }
      if (!isNaN(newLineNumber) && newLineNumber) {
        url += ('&newLineNumber=' + newLineNumber)
      }
      $.get(
        url,
        {
          dataType : 'html'
        },
        function(responseContent) {
          var tmp;
          if (!isNaN(oldLineNumber) && oldLineNumber) {
            if (!isNaN(newLineNumber) && newLineNumber) {
              tmp = getInlineContainer();
            } else {
              tmp = getInlineContainer('old');
            }
          } else {
            tmp = getInlineContainer('new');
          }
          tmp.addClass('inline-comment-form').children('.comment-box-container').html(responseContent);
          $tr.nextAll(':not(.not-diff):first').before(tmp);
        }
      );
    }
  }).on('click', 'table.diff .btn-default', function() {
    $(this).closest('.inline-comment-form').remove();
  });
  function renderOneCommitCommentIntoDiff($v, diff){
    var filename = $v.attr('filename'),
    oldline = $v.attr('oldline'), newline = $v.attr('newline');
    var tmp;
    var diff;
    if (typeof oldline !== 'undefined') {
      if (typeof newline !== 'undefined') {
        tmp = getInlineContainer();
      } else {
        tmp = getInlineContainer('old');
      }
      tmp.children('td:first').html($v.clone().show());
      diff.find('table.diff').find('.oldline[line-number=' + oldline  + ']')
      .parent().nextAll(':not(.not-diff):first').before(tmp);
    } else {
      tmp = getInlineContainer('new');
      tmp.children('td:last').html($v.clone().show());
      diff.find('table.diff').find('.newline[line-number=' + newline  + ']')
      .parent().nextAll(':not(.not-diff):first').before(tmp);
    }
    if (!diff.find('.toggle-notes').prop('checked')) {
      tmp.hide();
    }
  }
  function renderStatBar(add,del){
    if(add+del>5){
      if(add){
        if(add<del){
          add = Math.floor(1 + (add * 4 / (add+del)));
        }else{
          add = Math.ceil(1 + (add * 4 / (add+del)));
        }
      }
      del = 5-add;
    }
    var ret = $('<div class="diffstat-bar">');
    for(var i=0;i<5;i++){
      if(add){
        ret.append('<span class="text-diff-added">■</span>');
        add --;
      }else if(del){
        ret.append('<span class="text-diff-deleted">■</span>');
        del --;
      }else{
        ret.append('■');
      }
    }
    return ret;
  }
  function renderOneDiff(diffText, viewType){
    var table = diffText.closest("table[data-diff-id]");
    var i = table.data("diff-id");
    var ignoreWhiteSpace = table.find('.ignore-whitespace').prop('checked');
    diffUsingJS('oldText-'+i, 'newText-'+i, diffText.attr('id'), viewType, ignoreWhiteSpace);
    var add = diffText.find("table").attr("add")*1;
    var del = diffText.find("table").attr("del")*1;
    table.find(".diffstat").text(add+del+" ").append(renderStatBar(add,del)).attr("title",add+" additions & "+del+" deletions").tooltip();
    $('span.diffstat[data-diff-id="'+i+'"]').html('<span class="text-diff-added">+'+add+'</span><span class="text-diff-deleted">-'+del+'</span>').append(renderStatBar(add,del).attr('title',(add+del)+" lines changed").tooltip());

    @if(hasWritePermission) {
      diffText.find('.body').each(function(){ $('<b class="add-comment">+</b>').prependTo(this); });
    }
    @if(showLineNotes){
      var fileName = table.attr('filename');
      $('.inline-comment').each(function(i, v) {
        if($(this).attr('filename')==fileName){
          renderOneCommitCommentIntoDiff($(this), table);
        }
      });
    }
  }
  function renderDiffs(){
    var i=0, diffs = $('.diffText');
    function render(){
      if(diffs[i]){
        renderOneDiff($(diffs[i]), viewType);
        i++;
        setTimeout(render);
      }
    }
    render();
  }
});
</script>
